package com.tidc.seaservermodel.util;

import com.tidc.seaservermodel.config.RedisConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * redis工具类
 * @author: jamesluozhiwei
 */
@Component
@Slf4j
public class RedisUtil {


    private RedisTemplate redisTemplate;
    private static final long EXPIRATION_tIME = 2 * 60 * 60 * 1000;
    public boolean checkCode(String key,String code){
        String code2 = (String) get(key);
        if (code != null && code.equals(code2)) {
            return true;
        }
        return false;
    }
//  TODO  这个方法需要优化序列化器
    public int checkIp(HttpServletRequest req) {
        String ip = AccessAddressUtil.getRealIP(req);
        String key = RedisConfig.CHECK_IP + ip;
        String a = (String) get(key);
        if (a == null) {
            set(key, "1");
            return 200;
        }
        int count = Integer.parseInt(a);
        count += 1;
        log.info("ip {} 第 {} 次获取验证码",ip,count);
        if (count < 20) {
//            这里拿出来的是秒
            long keyExpire = getKeyExpire(key);
            keyExpire*=1000;
            set(key, count + "",keyExpire);
            return 200;
        }
        set(key, count + "", 24 * 60 * 60 * 1000);
        //到了20就给他报错
        log.error("有人恶意访问短信接口 ip {} 次数 {}", ip, count);
        return 500;
    }
    @Autowired
    public void setStringRedisTemplate(RedisTemplate redisTemplate) {
        JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
        //这个对String可能会有问题
        RedisSerializer<String> s = new StringRedisSerializer();
        redisTemplate.setKeySerializer(s);
        redisTemplate.setValueSerializer(jdkSerializationRedisSerializer);
        redisTemplate.setHashKeySerializer(s);
        redisTemplate.setHashValueSerializer(jdkSerializationRedisSerializer);
        this.redisTemplate = redisTemplate;
    }


//    public String getString(String key){
//        return stringRedisTemplate
//    }
    /**
     * 存入普通对象
     * @param key 键
     * @param value 值
     */
    public  void setObject(String key,Object value) {
        redisTemplate.opsForValue().set(key, value, EXPIRATION_tIME, TimeUnit.MILLISECONDS);
    }

    /**
     * 获取普通对象
     *
     * @param key 键
     * @return 对象
     */
    public Object getObject(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * 查询key,支持模糊查询
     * @param key
     * */
    public Set<String> keys(String key){
        return redisTemplate.keys(key);
    }

    /**
     * 字符串获取值
     * @param key
     * */
    public Object get(String key){
        return redisTemplate.opsForValue().get(key);

    }

    /**
     * 字符串存入值
     * 默认过期时间为2小时
     * @param key
     * */
    public void set(String key, String value){
        set(key,value,2 * 60 * 60 * 1000);
    }

    /**
     * 字符串存入值
     * @param expire 过期时间（毫秒计）
     * @param key
     * */
    public void set(String key, String value,long expire){
        redisTemplate.opsForValue().set(key,value, expire,TimeUnit.MILLISECONDS);
    }

    /**
     * 删出key
     * 这里跟下边deleteKey（）最底层实现都是一样的，应该可以通用
     * @param key
     * */
    public void delete(String key){
        redisTemplate.opsForValue().getOperations().delete(key);
    }

    /**
     * 添加单个
     * @param key    key
     * @param filed  filed
     * @param domain 对象
     */
    public void hset(String key,String filed,Object domain){
        hset(key,filed,domain,2 * 60 * 60 * 1000);
    }

    /**
     * 添加单个
     * @param key    key
     * @param filed  filed
     * @param domain 对象
     * @param expire 过期时间（毫秒计）
     */
    public void hset(String key,String filed,Object domain,long expire){
        redisTemplate.opsForHash().put(key, filed, domain);
        setKeyExpire(key,2 * 60 * 60 * 1000);
    }

    /**
     * 添加HashMap
     *
     * @param key    key
     * @param hm    要存入的hash表
     */
    public void hset(String key, HashMap<String,Object> hm){
        redisTemplate.opsForHash().putAll(key,hm);
        setKeyExpire(key,2 * 60 * 60 * 1000);
    }

    /**
     * 如果key存在就不覆盖
     * @param key
     * @param filed
     * @param domain
     */
    public void hsetAbsent(String key,String filed,Object domain){
        redisTemplate.opsForHash().putIfAbsent(key, filed, domain);
    }

    /**
     * 查询key和field所确定的值
     * @param key 查询的key
     * @param field 查询的field
     * @return HV
     */
    public Object hget(String key,String field) {
        return redisTemplate.opsForHash().get(key, field);
    }

    /**
     * 查询该key下所有值
     * @param key 查询的key
     * @return Map<HK, HV>
     */
    public Object hget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * 删除key下所有值
     *
     * @param key 查询的key
     */
    public void deleteKey(String key) {
        redisTemplate.opsForHash().getOperations().delete(key);
    }

    /**
     * 添加set集合
     * @param key
     * @param set
     * @param expire
     */
    public void sset(Object key,Set<?> set,long expire){
        redisTemplate.opsForSet().add(key,set);
        setKeyExpire(key,expire);
    }

    /**
     * 添加set集合
     * @param key
     * @param set
     */
    public void sset(Object key,Set<?> set){
        sset(key, set,2 * 60 * 60 * 1000);
    }

    /**
     * 判断key和field下是否有值
     * @param key 判断的key
     * @param field 判断的field
     */
    public Boolean hasKey(String key,String field) {
        return redisTemplate.opsForHash().hasKey(key,field);
    }

    /**
     * 判断key下是否有值
     * @param key 判断的key
     */
    public Boolean hasKey(String key) {
        return redisTemplate.opsForHash().getOperations().hasKey(key);
    }

    /**
     * 更新key的过期时间
     * @param key
     * @param expire
     */
    public void setKeyExpire(Object key,long expire){
        redisTemplate.expire(key,expire,TimeUnit.MILLISECONDS);
    }
    public long getKeyExpire(Object key){
        return redisTemplate.getExpire(key);
    }
    public void setListObject(Object key,Object value){
        redisTemplate.opsForList().leftPush(key,value);
    }
}
